package tr.edu.metu.is.mega.server.business;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import tr.edu.metu.is.mega.common.dto.ActivityDTO;
import tr.edu.metu.is.mega.common.dto.CourseDTO;
import tr.edu.metu.is.mega.common.dto.CourseStudentDTO;
import tr.edu.metu.is.mega.common.dto.TeamDTO;
import tr.edu.metu.is.mega.common.dto.UserDTO;
import tr.edu.metu.is.mega.server.dao.CourseDAO;
import tr.edu.metu.is.mega.server.dao.DatabaseConnectionFactory;
import tr.edu.metu.is.mega.server.dao.TeamDAO;
import tr.edu.metu.is.mega.server.dao.UserDAO;
import tr.edu.metu.is.mega.server.entity.Course;
import tr.edu.metu.is.mega.server.entity.Systemuser;
import tr.edu.metu.is.mega.server.entity.Team;

import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.extensions.When;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

/**
 * Class to manage courses.
 */
public class CourseManager {

    private final CourseDAO dao;

    private final TeamDAO teamDAO;

    private final CourseDTOHelper helper;

    private final UserDAO userDAO;

    private final UserDTOHelper userDTOHelper;

    /**
     * Default constructor.
     */
    public CourseManager() {
        dao = new CourseDAO();
        teamDAO = new TeamDAO();
        helper = new CourseDTOHelper();
        userDAO = new UserDAO();
        userDTOHelper = new UserDTOHelper();
    }

    /**
     * Finds course with given id.
     * 
     * @param id course id
     * @return found course
     */
    public CourseDTO findById(int id) {
        return helper.convertToDTO(dao.findById(id));
    }

    /**
     * Creates a new course record.
     * 
     * @param course course instance
     * @return created user instance
     */
    public CourseDTO createCourse(CourseDTO course) {
        Course entity = new Course();
        helper.convertToEntity(course, entity);
        Course create = dao.create(entity);
        return helper.convertToDTO(create);
    }

    /**
     * Updates a course record.
     * 
     * @param course course instance
     * @return updated course instance
     */
    public CourseDTO updateCourse(CourseDTO course) {
        Course entity = dao.findById(course.getPkid());
        helper.convertToEntity(course, entity);
        Course update = dao.update(entity);
        return helper.convertToDTO(update);
    }

    /**
     * Deletes a course record
     * 
     * @param course course to be deleted
     */
    public void deleteCourse(CourseDTO course) {
        Connection con = DatabaseConnectionFactory.getConnection();
        Statement stmt = null;
        try {
            stmt = con.createStatement();
            stmt.executeUpdate("DELETE FROM lecturenote WHERE fk_courseid=" + course.getPkid());
            stmt.executeUpdate("DELETE FROM announcement WHERE fk_courseid=" + course.getPkid());

            stmt.executeUpdate("DELETE FROM reviewer WHERE fk_activityid IN (SELECT pkid FROM activity where activity.fk_courseid="
                    + course.getPkid() + ")");

            stmt.executeUpdate("DELETE FROM submissionrevision WHERE fk_submission IN (select pkid FROM submission WHERE fk_activity IN (SELECT pkid FROM activity where activity.fk_courseid="
                    + course.getPkid() + "))");

            stmt.executeUpdate("DELETE FROM submission WHERE fk_activity IN (SELECT pkid FROM activity where activity.fk_courseid="
                    + course.getPkid() + ")");

            stmt.executeUpdate("DELETE FROM activity where activity.fk_courseid=" + course.getPkid());

            stmt.executeUpdate("DELETE FROM teammember WHERE fk_teamid IN (SELECT pkid FROM team where fk_courseid=" + course.getPkid() + ")");

            stmt.executeUpdate("DELETE FROM team where fk_courseid=" + course.getPkid());

            stmt.executeUpdate("DELETE FROM coursestudent where fk_courseid=" + course.getPkid());
            stmt.executeUpdate("DELETE FROM courseassistant where fk_courseid=" + course.getPkid());
            stmt.executeUpdate("DELETE FROM course where pkid=" + course.getPkid());
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            try {
                stmt.close();
            } catch (Exception e) {
            }
            try {
                con.close();
            } catch (Exception e) {
            }
        }

    }

    /**
     * Returns all courses.
     * 
     * @return list of courses
     */
    public List<CourseDTO> getAllCourses() {
        return null;
    }

    /**
     * Returns courses of a teacher.
     * 
     * @param teacherId teacher identifier
     * @return list of courses
     */
    public List<CourseDTO> getCoursesByTeacher(int teacherId) {
        return null;
    }

    /**
     * Returns courses of a student.
     * 
     * @param studentId student identifier
     * @return list of courses
     */
    public List<CourseDTO> getCoursesByStudent(int studentId) {
        return null;
    }

    /**
     * Queries and returns courses matching criteria.
     * 
     * @param filter filter instance
     * @return list of courses
     */
    public List<CourseDTO> getCourses(CourseDTO filter) {
        Course entity = new Course();
        helper.convertToEntity(filter, entity);
        List<Course> entities = dao.findByExample(entity, true);
        return helper.toDTO(entities);
    }

    /**
     * Pulls and returns list of students from METU Online.
     * 
     * @param course course instance
     * @return list of students
     */
    public List<CourseStudentDTO> pullStudentsFromMETUOnline(CourseDTO course) {
        List<CourseStudentDTO> list = new ArrayList<CourseStudentDTO>();
        try {
            InputStream is = getClass().getResourceAsStream("/metuonline.properties");
            Properties props = new Properties();
            props.load(is);
            for (Object o : props.keySet()) {
                String userid = (String) o;
                StringTokenizer st = new StringTokenizer(props.getProperty(userid), "|");
                String name = st.nextToken();
                String surname = name.substring(name.lastIndexOf(" ")).trim();
                name = name.substring(0, name.lastIndexOf(" ")).trim();
                String email = st.nextToken();
                Systemuser user = new Systemuser();
                user.setUsername(userid);
                List<Systemuser> users = userDAO.findByExample(user, false);
                if (users.size() == 1) {
                    user = users.get(0);
                }
                user.setName(name);
                user.setSurname(surname);
                user.setEmail(email);
                user.setIdentificationno(userid);
                user.setUserrole("S");
                user.setPassword(userid);
                if (user.getPkid() != null) {
                    userDAO.update(user);
                } else {
                    userDAO.create(user);
                }
                UserDTO userDTO = userDTOHelper.convertToDTO(user);
                // MailService.welcomeUser(userDTO);
                CourseStudentDTO studentDTO = new CourseStudentDTO();
                studentDTO.setCourse(course);
                studentDTO.setUser(userDTO);

                list.add(studentDTO);
            }
            userDAO.getEntityManager().clear();
        } catch (Exception ex) {
            throw new RuntimeException();
        }
        return list;
    }

    /**
     * @param team
     * @return
     */
    public CourseDTO updateTeam(TeamDTO dto) {
        Team team = teamDAO.findById(dto.getPkid());
        team.setLogo(dto.getLogo());
        team.setTeamname(dto.getTeamName());
        teamDAO.update(team);
        dao.getEntityManager().clear();
        return helper.convertToDTO(dao.findById(dto.getCourse().getPkid()));
    }

    public boolean exportToGoogleCalendar(String userName, String password, CourseDTO course) {
        CalendarService myService = new CalendarService("mega-exampleApp-1.0");
        try {
            myService.setUserCredentials(userName, password);

            URL postURL = new URL("http://www.google.com/calendar/feeds/" + userName + "/private/full");

            List<ActivityDTO> activities = course.getActivities();

            for (ActivityDTO dto : activities) {

                CalendarEventEntry myEvent = new CalendarEventEntry();
                // Set the title and description
                myEvent.setTitle(new PlainTextConstruct(course.getBasicInfo() + " " + dto.getDescription()));
                myEvent.setContent(new PlainTextConstruct(dto.toString()));

                // Create DateTime events and create a When object to hold them,
                // then add
                // the When event to the event
                DateTime startTime = new DateTime(dto.getAlertTime());
                DateTime endTime = new DateTime(dto.getDueDate());
                When eventTimes = new When();
                eventTimes.setStartTime(startTime);
                eventTimes.setEndTime(endTime);
                myEvent.addTime(eventTimes);

                // POST the request and receive the response:

                CalendarEventEntry insertedEntry = myService.insert(postURL, myEvent);
                System.out.println(insertedEntry);

            }
            return true;
        } catch (AuthenticationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ServiceException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }

}
